/*************************************************************************
 > File Name: monolith/interface/sql/sql_face.cc
 > Author: dzhang
 > Mail: dong.zhang@ingenic.com
 > Created Time: Thu 04 Feb 2021 10:33:27 AM CST
 ************************************************************************/

#include "monolith/interface/sql/sql_face.h"
#include <iostream>
#include "absl/strings/str_cat.h"
#include "monolith/util/base64.h"
#include "monolith/interface/inference/utils.h"

CC_NAME_SPACE_BEGIN
namespace sql {

SQLFace* SQLFace::get_instance() {
    static SQLFace instance;
    return &instance;
}

int SQLFace::insert_face(std::vector<float> &face_feature,
        FaceInfo& face_info) {
    auto feature_base64_str = ml::util::base64_encode(
            (unsigned char*) face_feature.data(), face_feature.size() * 4);
    std::string feature_str((char*) feature_base64_str);
    std::string name = absl::StrCat("\"", face_info.name, "\",");
    std::string feature = absl::StrCat("\"", feature_str, "\",");
    std::string attr = absl::StrCat("\"", face_info.attr, "\"");
    std::string insert_cmd = absl::StrCat("INSERT INTO face VALUES (NULL,",
            name, feature, attr, ")");
    auto nb = ml::sql::SQLFace::get_instance()->exec(insert_cmd);
    return nb;
}

int SQLFace::query_face(std::vector<float> &face_feature, float threshold,
        FaceInfo& face_info) {
    int dataset_num = ml::sql::SQLFace::get_instance()->execAndGet(
            "SELECT COUNT(name) FROM face");
    if (dataset_num == 0) {
        return 0;
    }
    for (int i = 1; i <= dataset_num; i++) {
        std::string select_cmd = absl::StrCat(
                "SELECT feature FROM face WHERE id=", i);
        std::string feature_str = ml::sql::SQLFace::get_instance()->execAndGet(
                select_cmd);
        std::vector<float> current_feature;
        unsigned char *feature_ptr = ml::util::base64_decode(
                (unsigned char*) feature_str.c_str());
        for (int i = 0; i < face_feature.size(); i++) {
            current_feature.push_back(((float*) feature_ptr)[i]);
        }
        auto dis = ml::inference::distance(face_feature, current_feature);
        // LOG(INFO)<< dis;
        if (dis < threshold) {
            std::string select_cmd = absl::StrCat(
                    "SELECT name FROM face WHERE id=", i);
            std::string name = ml::sql::SQLFace::get_instance()->execAndGet(
                    select_cmd);
            face_info.name = name;
            face_info.dis = dis;
        }
    }
    return 0;
}

SQLFace::SQLFace() {
}
;

SQLFace::~SQLFace() {
}
;

SQLFace::SQLFace(const SQLFace &signal) {
}
;

const SQLFace& SQLFace::operator=(const SQLFace &signal) {
}
;

} // namespace sql
CC_NAME_SPACE_END

